_require local "../../../../basis.smi"
(* _require local "../../../../smlnj-lib/Util/binary-set-fn.smi" *)
(* _require local "../../../libs/env/main/SEnv.smi" *)
_require local "../../../extensions/debug/main/Bug.smi"
_require local "../../../extensions/format-utils/main/SmlppgUtil.ppg.smi"

_require local "../../../extensions/usererror/main/UserErrorUtils.smi"
_require local "./NameEvalError.ppg.smi"

_require "../../../data/symbols/main/Loc.smi"
_require "../../../../smlformat-lib.smi"
_require "../../../libs/ids/main/LocalID.smi"
_require "../../../data/symbols/main/Symbol.smi"
_require "../../../libs/util/main/TermFormat.smi"
_require "../../../compilerIRs/idcalc/main/IDCalc.ppg.smi"
_require "../../../data/types/main/Types.ppg.smi"

structure NameEvalEnv =
struct
  type varE = IDCalc.varE
  datatype tstr
    =  TSTR of {tfun : IDCalc.tfun, defRange:Loc.loc}
    |  TSTR_DTY of {tfun:IDCalc.tfun,
                    varE:varE,
                    defRange:Loc.loc,
                    formals:IDCalc.formals, conSpec:IDCalc.conSpec}
  type tyE = tstr SymbolEnv.map
  datatype strKind =
      SIGENV of SignatureID.id
    | STRENV of StructureID.id
    | FUNAPP of {id:StructureID.id,funId:FunctorID.id,argId:StructureID.id}
(* 2016-11-06 ohori: interfaceでのfunctor argumentをfunctor replicationに
  使用禁止するための暫定措置
  参照：bug 331_functorSmi-a
  FUNARGはSTRENVと同等の振る舞い．
  ただし，interfaceの中でのstructure replicationを禁止．
 *)
    | FUNARG of StructureID.id
  datatype strE
    = STR of {env:env, strKind:strKind, loc:Loc.loc, 
              definedSymbol:Symbol.longsymbol} SymbolEnv.map
  and env
    = ENV of {varE: varE, tyE: tyE, strE: strE}
  type strEntry = {env:env, strKind:strKind, loc:Loc.loc, 
                   definedSymbol:Symbol.longsymbol}
  type sigEntry = {env:env, sigId:SignatureID.id, loc:Loc.loc}
  type funEEntry = 
       {id: FunctorID.id,
        loc: Loc.loc,
        version:IDCalc.version,
        argSigEnv: env,
        argStrEntry: strEntry,
        argStrName: Symbol.symbol,
        dummyIdfunArgTy: IDCalc.ty option,
        polyArgTys: IDCalc.ty list,
        typidSet: TypID.Set.set,
        exnIdSet: ExnID.Set.set,
        bodyEnv: env,
        bodyVarExp: IDCalc.icexp}
  type funE = funEEntry SymbolEnv.map
  type sigE = sigEntry SymbolEnv.map
  type topEnv = {Env:env, FunE:funE, SigE: sigE}
  type sigEList = (Symbol.symbol * env) list
  val format_tstr : tstr -> SMLFormat.FormatExpression.expression list
  val format_tyE : tyE -> SMLFormat.FormatExpression.expression list
  val format_strE : strE -> SMLFormat.FormatExpression.expression list
  val format_strEntry
      : strEntry -> SMLFormat.FormatExpression.expression list
  val format_env : env -> TermFormat.format
  val format_funEEntry
      : funEEntry -> SMLFormat.FormatExpression.expression list
  val printTy_env
      : {env: 'a, 
         tfunName: 'a * IDCalc.tfun -> string, 
         tyConName: 'a * Types.tyCon -> string} 
        * TermFormat.format * TermFormat.format -> env -> TermFormat.format
  val printTy_sigE
      : {env: 'a, 
         tfunName: 'a * IDCalc.tfun -> string, 
         tyConName: 'a * Types.tyCon -> string} 
        * TermFormat.format * TermFormat.format -> sigE -> TermFormat.format
  val printTy_sigEList
      : {env: env list, 
         tfunName: env list * IDCalc.tfun -> string, 
         tyConName: env list * Types.tyCon -> string} 
        * TermFormat.format * TermFormat.format
        -> sigEList -> TermFormat.format
  val printTy_funEEntry
      : {env: env list, 
         tfunName: env list * IDCalc.tfun -> string, 
         tyConName: env list * Types.tyCon -> string} 
        * TermFormat.format * TermFormat.format
        -> funEEntry -> SMLFormat.FormatExpression.expression list

  val format_funE : funE -> SMLFormat.FormatExpression.expression list
  val format_sigE : sigE -> SMLFormat.FormatExpression.expression list
  val format_topEnv : topEnv -> SMLFormat.FormatExpression.expression list
  val tstrFormals : tstr -> IDCalc.formals
  val tstrLiftedTys : tstr -> IDCalc.liftedTys
  val tstrArity : tstr -> int
  val tstrToString : tstr -> string
  val tyEToString : tyE -> string
  val envToString : env -> string
  val topEnvToString : topEnv -> string
  val funEToString : funE -> string

  val emptyTyE : tyE
  val emptyEnv : env
  val emptyTopEnv : topEnv
  val findTstr : env * Symbol.longsymbol -> (Symbol.symbol * tstr) option
  val findId : env * Symbol.longsymbol -> (Symbol.symbol * IDCalc.idstatus) option


  val replaceLocTyE : Loc.loc -> tyE -> tyE
  val replaceLocVarE : Loc.loc -> varE -> varE
  val replaceLocStrEntry : Loc.loc -> strEntry -> strEntry
  val replaceLocStrE : Loc.loc -> strE -> strE
  val replaceLocEnv : Loc.loc -> env -> env

end
